<template>
  <div class="canvas">
    <div class="inputBox">
      <input
        id="deleteCanvas"
        type="button"
        value="清空坐标"
        @click="ClickClear"
      />
      <input id="putCanvas" type="button" value="提交坐标" @click="ClickPut" />
      <input
        id="drawCanvas"
        type="button"
        value="绘制坐标"
        @click="ClickDraw"
      />
      <input
        id="resetCanvas"
        type="button"
        value="重置坐标"
        @click="ClickReset"
      />
      <input id="setCanvas" type="button" value="生成坐标" @click="ClickSet" />
    </div>
    <div class="canvasBox">
      <img ref="img" class="img" src="../assets/OIP2.jpg" alt />
      <!--用来和鼠标进行交互操作的canvas-->
      <canvas
        id="canvas"
        :class="isReset ? 'borderRed' : ''"
        @click="ClickDrawPoint"
        @mousemove="MouseMove"
        width="1000"
        height="600"
      ></canvas>
      <!--存储已生成的点线，避免被清空-->
      <canvas id="canvasSave" width="1000" height="600"></canvas>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      can: null,
      ctx: null,
      canSave: null,
      ctxSave: null,
      pointX: null,
      pointY: null,
      drawEnd: true, // 结束绘制
      isReset: false, // 是否重置
      pointArr: [], //存放坐标的数组
      pointArrSave: [], //保存存放坐标的数组
      oIndex: -1, //判断鼠标是否移动到起始点处，-1为否，1为是
      ctxFillStyle: "rgba(161,195,255,0)", // 填充颜色
      ctxSaveFillStyle: "rgba(161,195,255,0)", // 填充颜色
      arcFillStyle: "rgba(178,34,34,1)", // 圆点的填充颜色
    };
  },
  mounted() {
    this.can = document.getElementById("canvas");
    this.ctx = this.can.getContext("2d");
    this.canSave = document.getElementById("canvasSave");
    this.ctxSave = this.canSave.getContext("2d");
    this.ctx.strokeStyle = "rgba(178,34,34,1)"; //线条颜色
    this.ctx.lineWidth = 1; //线条粗细
    this.ctxSave.strokeStyle = "rgba(178,34,34,1)"; //线条颜色
    this.ctxSave.lineWidth = 1; //线条粗细
  },
  methods: {
    // 绘制坐标
    ClickDraw() {
      this.drawEnd = false;
      this.isReset = false;
    },
    // 生成坐标
    ClickSet() {
      this.isReset = false;
      this.ClickClear();
      let dataTest = "[[3,3],[1,178],[254,4]]";
      JSON.parse(dataTest).forEach((item, index) => {
        this.pointArr.push({
          x: item[0] / this.getZoomRatio().scaleX,
          y: item[1] / this.getZoomRatio().scaleY,
        });
      });
      console.log("生成坐标", this.pointArr);
      this.canvasSave(this.pointArr); //保存点线同步到另一个canvas
      this.saveCanvas(); //生成画布
    },
    // 重置坐标
    ClickReset() {
      this.isReset = true;
      this.ClickClear();
    },
    // 提交坐标
    ClickPut() {
      let data = null;
      if (this.pointArrSave.length > 0) {
        this.pointArrSave.forEach((item, index) => {
          item[0] = parseInt(item[0] * this.getZoomRatio().scaleX);
          item[1] = parseInt(item[1] * this.getZoomRatio().scaleY);
        });
        data = JSON.stringify(this.pointArrSave);
      }
      console.log("提交坐标", data);
    },
    //   点击画点
    ClickDrawPoint(e) {
      if (!this.drawEnd) {
        if (e.offsetX || e.layerX) {
          this.pointX = e.offsetX == undefined ? e.layerX : e.offsetX;
          this.pointY = e.offsetY == undefined ? e.layerY : e.offsetY;
          let piX, piY;
          if (this.oIndex > 0 && this.pointArr.length > 0) {
            piX = this.pointArr[0].x;
            piY = this.pointArr[0].y;
            //画点
            this.makearc(
              this.ctx,
              piX,
              piY,
              this.GetRandomNum(2, 2),
              0,
              180,
              this.arcFillStyle
            );
            this.pointArr.push({ x: piX, y: piY });
            this.canvasSave(this.pointArr); //保存点线同步到另一个canvas
            this.saveCanvas(); //生成画布
          } else {
            piX = this.pointX;
            piY = this.pointY;
            this.makearc(
              this.ctx,
              piX,
              piY,
              this.GetRandomNum(2, 2),
              0,
              180,
              this.arcFillStyle
            );
            this.pointArr.push({ x: piX, y: piY });
            this.canvasSave(this.pointArr); //保存点线同步到另一个canvas
          }
        }
      }
    },
    // 鼠标移动
    MouseMove(e) {
      if (e.offsetX || e.layerX) {
        this.pointX = e.offsetX == undefined ? e.layerX : e.offsetX;
        this.pointY = e.offsetY == undefined ? e.layerY : e.offsetY;
        let piX, piY;
        /*清空画布*/
        this.ctx.clearRect(0, 0, this.can.width, this.can.height);
        /*鼠标下跟随的圆点*/
        this.makearc(
          this.ctx,
          this.pointX,
          this.pointY,
          this.GetRandomNum(4, 4),
          0,
          180,
          this.arcFillStyle
        );

        if (this.pointArr.length > 0) {
          if (
            this.pointX > this.pointArr[0].x - 15 &&
            this.pointX < this.pointArr[0].x + 15 &&
            this.pointY > this.pointArr[0].y - 15 &&
            this.pointY < this.pointArr[0].y + 15
          ) {
            if (this.pointArr.length > 1) {
              piX = this.pointArr[0].x;
              piY = this.pointArr[0].y;
              this.ctx.clearRect(0, 0, this.can.width, this.can.height);
              this.makearc(
                this.ctx,
                piX,
                piY,
                this.GetRandomNum(4, 4),
                0,
                180,
                this.arcFillStyle
              );
              this.oIndex = 1;
            }
          } else {
            piX = this.pointX;
            piY = this.pointY;
            this.oIndex = -1;
          }
          /*开始绘制*/
          this.ctx.beginPath();
          this.ctx.moveTo(this.pointArr[0].x, this.pointArr[0].y);
          if (this.pointArr.length > 1) {
            for (var i = 1; i < this.pointArr.length; i++) {
              this.ctx.lineTo(this.pointArr[i].x, this.pointArr[i].y);
            }
          }
          this.ctx.lineTo(piX, piY);
          this.ctx.fillStyle = this.ctxFillStyle; //填充颜色
          this.ctx.fill(); //填充
          this.ctx.stroke(); //绘制
        }
      }
    },
    // 存储已生成的点线
    canvasSave(pointArr) {
      this.ctxSave.clearRect(0, 0, this.ctxSave.width, this.ctxSave.height);
      this.ctxSave.beginPath();
      if (pointArr.length > 1) {
        this.ctxSave.moveTo(pointArr[0].x, pointArr[0].y);
        for (let i = 1; i < pointArr.length; i++) {
          this.ctxSave.lineTo(pointArr[i].x, pointArr[i].y);
          this.ctxSave.fillStyle = this.ctxSaveFillStyle; //填充颜色
          this.ctxSave.fill();
          this.ctxSave.stroke(); //绘制
        }
        this.ctxSave.closePath();
      }
    },
    /*生成画布 结束绘画*/
    saveCanvas() {
      this.ctx.clearRect(0, 0, this.can.width, this.can.height);
      this.drawEnd = true;
      this.ctxSave.closePath(); //结束路径状态，结束当前路径，如果是一个未封闭的图形，会自动将首尾相连封闭起来
      this.ctxSave.fill(); //填充
      this.ctxSave.stroke(); //绘制
      if (
        this.pointArr[0].x === this.pointArr[this.pointArr.length - 1].x &&
        this.pointArr[0].y === this.pointArr[this.pointArr.length - 1].y
      ) {
        this.pointArr.pop();
      }
      this.pointArr.forEach((item, index) => {
        this.pointArrSave.push([item.x, item.y]);
      });
      this.pointArr = [];
    },
    /*清空选区*/
    ClickClear() {
      this.ctx.clearRect(0, 0, this.can.width, this.can.height);
      this.ctxSave.clearRect(0, 0, this.canSave.width, this.canSave.height);
      this.pointArr = [];
      this.pointArrSave = [];
      this.drawEnd = true;
    },
    /*验证canvas画布是否为空函数*/
    isCanvasBlank(canvas) {
      let blank = document.createElement("canvas"); //创建一个空canvas对象
      blank.width = canvas.width;
      blank.height = canvas.height;
      return canvas.toDataURL() == blank.toDataURL(); //为空 返回true
    },
    /*canvas生成圆点*/
    GetRandomNum(Min, Max) {
      let Range = Max - Min;
      let Rand = Math.random();
      return Min + Math.round(Rand * Range);
    },
    makearc(ctx, x, y, r, s, e, color) {
      ctx.clearRect(0, 0, this.can.width, this.can.height); //清空画布
      ctx.beginPath();
      ctx.fillStyle = color;
      ctx.arc(x, y, r, s, e);
      ctx.fill();
    },
    // 获取缩放比例
    getZoomRatio() {
      let img = this.$refs.img;
      let naturalWidth = parseInt(img.naturalWidth);
      let naturalHeight = parseInt(img.naturalHeight);
      let width = parseInt(img.width);
      let height = parseInt(img.height);
      return {
        scaleX: naturalWidth / width,
        scaleY: naturalHeight / height,
      };
    },
  },
};
</script>
<style lang="scss" scoped>
.canvas {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  .inputBox {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 20px 0;
    input {
      width: 100px;
      font-size: 16px;
      margin: 0 5px;
    }
  }
  .canvasBox {
    width: 1000px;
    height: 600px;
    position: relative;
    canvas {
      // border: 2px solid transparent;
      display: block;
      width: 1000px;
      height: 600px;
    }
    .borderRed {
      // border: 2px solid #ff3d3d;
      box-shadow: 0 0 0 2px #ff3d3d inset;
    }
    #canvas {
      position: absolute;
      z-index: 1;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      cursor: crosshair;
    }

    #canvasSave {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    .img {
      width: 100%;
      height: 100%;
    }
  }
}
</style>